﻿#region Imports
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using CommonUtilities.Enums;
using CommonUtilities.Util;
#endregion

namespace CommonUtilities.Extensions
{
    /// <summary>
    /// Extension methods for collections
    /// </summary>
    /// <seealso cref="http://michlg.wordpress.com/category/programming/net/wpf/" />
    public static class CollectionExtensions
    {
        // DOCUM_CLEANUP

        #region Extension methods
        #region Dictionary
        /// <summary>
        /// Gets the value from the specified &lt;<paramref name="key"/>&gt; in the dictionary &lt;<paramref name="source"/>&gt;
        /// <para>Returns default value of type <paramref name="TKey"/>, if &lt;<paramref name="key"/>&gt; is not found</para>
        /// </summary>
        /// <typeparam name="TKey">The type of the keys in the dictionary</typeparam>
        /// <typeparam name="TValue">The type of the values in the dictionary</typeparam>
        /// <param name="source">A <code>System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;</code> containing data</param>
        /// <param name="key">Key to searched with</param>
        /// <param name="throwException">TRUE: throws exception when given key is not found in dictionary
        /// <para>FALSE: supresses exception</para></param>
        /// <returns>Value against the specified &lt;<paramref name="key"/>&gt;; default value of type <paramref name="TKey"/>, if &lt;<paramref name="key"/>&gt; is not found</returns>
        public static TValue GetValueFromKey<TKey, TValue>(this Dictionary<TKey, TValue> source, TKey key, bool ignoreStringCase = false, bool throwException = false)
        {
            if (source.IsNull()) return throwException ? source[key] : default(TValue);

            if (key is string && ignoreStringCase)
                return (TValue)Convert.ChangeType(source._Where(pair => pair.Key.ToString().ToLower() == key.ToString().ToLower()).FirstOrDefault().Coalesce(new KeyValuePair<TKey, TValue>()).Value, typeof(string));
            else if (source.Keys.Contains(key) || throwException) return source[key];
            else return default(TValue);
        }

        /// <summary>
        /// Gets the value from the specified &lt;<paramref name="value"/>&gt; in the dictionary &lt;<paramref name="source"/>&gt;
        /// <para>Returns default value of type <paramref name="TValue"/>, if &lt;<paramref name="value"/>&gt; is not found</para>
        /// </summary>
        /// <typeparam name="TKey">The type of the keys in the dictionary</typeparam>
        /// <typeparam name="TValue">The type of the values in the dictionary</typeparam>
        /// <param name="source">A <code>System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;</code> containing data</param>
        /// <param name="value">Value to searched with</param>
        /// <param name="ignoreStringCase"></param>
        /// <param name="throwException">TRUE: throws exception when given value is not found in dictionary
        /// <para>FALSE: supresses exception</para></param>
        /// <returns>Value against the specified &lt;<paramref name="key"/>&gt;; default value of type <paramref name="TKey"/>, if &lt;<paramref name="key"/>&gt; is not found</returns>
        public static TKey GetKeyFromValue<TKey, TValue>(this Dictionary<TKey, TValue> source, TValue value, bool ignoreStringCase, bool throwException = false)
        {
            try
            {
                if (source.IsNull() && !throwException) return default(TKey);

                if (typeof(TValue) != typeof(string)) ignoreStringCase = false;

                if (!ignoreStringCase & source.ContainsValue(value)) // Match with case-check
                    return ExtractValueByKey<TKey, TValue>(source, value, ignoreStringCase);
                else if (ignoreStringCase && typeof(TValue) == typeof(string)) // Match with no case-check
                    return ExtractValueByKey<TKey, TValue>(source, value, ignoreStringCase);
                else // No match
                {
                    if (throwException) return ExtractValueByKey<TKey, TValue>(source, value, false);
                    else return default(TKey);
                }
            }
            catch (Exception) { if (throwException) throw; else return default(TKey); }
        }

        private static TKey ExtractValueByKey<TKey, TValue>(Dictionary<TKey, TValue> source, TValue value, bool ignoreStringCase)
        {
            if (ignoreStringCase)
                return source.Where(pair => pair.Value.ToString().ToLower() == value.ToString().ToLower()).FirstOrDefault().Key;
            else
                return source.Where(pair => pair.Value.Equals(value)).FirstOrDefault().Key;
        }

        /// <summary>
        /// Adds the specified key and value to the dictionary.
        /// </summary>
        /// <typeparam name="TKey">The type of the keys in the dictionary</typeparam>
        /// <typeparam name="TValue">The type of the values in the dictionary</typeparam>
        /// <param name="source">A <code>System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;</code> containing data</param>
        /// <param name="key">The key of the element to add.</param>
        /// <param name="value">The value of the element to add. The value can be null for reference types.</param>
        /// <exception cref="System.ArgumentNullException">key is null.</exception>
        /// <exception cref="System.ArgumentException">An element with the same key already exists in the <code>System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;.</code></exception>
        public static Dictionary<TKey, TValue> AddToDictionary<TKey, TValue>(this Dictionary<TKey, TValue> source, TKey key, TValue value)
        {
            if (source.IsNull()) source = new Dictionary<TKey, TValue>();

            if (!source.ContainsKey(key)) source.Add(key, value);
            else source[key] = value;

            return source;
        }

        /// <summary>
        /// Adds the specified key and value to the dictionary.
        /// </summary>
        /// <typeparam name="TKey">The type of the keys in the dictionary</typeparam>
        /// <param name="source">A <code>System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;</code> containing data</param>
        /// <param name="key">The key of the element to add.</param>
        /// <exception cref="System.ArgumentNullException">key is null.</exception>
        /// <exception cref="System.ArgumentException">An element with the same key already exists in the <code>System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;.</code></exception>
        public static Dictionary<TKey, TKey> AddToDictionary<TKey>(this Dictionary<TKey, TKey> source, TKey key)
        {
            return source.AddToDictionary(key, key);
        }

        /// <summary>
        /// Determines whether the <code>System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;</code> contains the specified key.
        /// </summary>
        /// <typeparam name="TKey">The type of the keys in the dictionary</typeparam>
        /// <typeparam name="TValue">The type of the values in the dictionary</typeparam>
        /// <param name="source">A <code>System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;</code> containing data</param>
        /// <param name="key">The key to locate in the <code>System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;.</code></param>
        /// <returns>
        /// TRUE if the <code>System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;</code> contains an element with the specified key;
        /// <para>otherwise, FALSE</para>
        /// </returns>
        /// <exception cref="System.ArgumentNullException">key is null.</exception>
        public static bool _ContainsKey<TKey, TValue>(this Dictionary<TKey, TValue> source, TKey key)
        {
            if (source.GetValueFromKey(key).IsDefault()) return false;
            else return source.ContainsKey(key);
        }

        /// <summary>
        /// Determines whether the <code>System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;</code> contains a specific value.
        /// </summary>
        /// <typeparam name="TKey">The type of the keys in the dictionary</typeparam>
        /// <typeparam name="TValue">The type of the values in the dictionary</typeparam>
        /// <param name="source">A <code>System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;</code> containing data</param>
        /// <param name="value">The value to locate in the <code>System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;.</code> The value can be null for reference types.</param>
        /// <param name="ignoreStringCase">TRUE: ignores case in case of string</param>
        /// <returns>
        /// TRUE if the <code>System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;</code> contains an element with the specified value;
        /// <para>otherwise, FALSE</para>
        /// </returns>
        public static bool _ContainsValue<TKey, TValue>(this Dictionary<TKey, TValue> source, TValue value, bool ignoreStringCase)
        {
            if (typeof(TValue) != typeof(string)) ignoreStringCase = false;

            if (!ignoreStringCase & source.GetKeyFromValue(value, ignoreStringCase).IsDefault()) // Checking if key available against specified value
                return false;
            else if (ignoreStringCase) // Case check for string value
                return source.Where(pair => pair.Value.ToString().ToLower() == value.ToString().ToLower())._Any();
            else // General checking
                return source.ContainsValue(value);
        }

        /// <summary>
        /// Converts a <code>IEnumerable&lt;KeyValuePair&lt;<typeparamref name="TInKey"/>, <typeparamref name="TInValue"/>&gt;&gt;</code>
        /// to a <code>Dictionary&lt;<typeparamref name="TOutKey"/>, <typeparamref name="TOutValue"/>&gt;</code>
        /// </summary>
        /// <typeparam name="TInKey"></typeparam>
        /// <typeparam name="TInValue"></typeparam>
        /// <typeparam name="TOutKey"></typeparam>
        /// <typeparam name="TOutValue"></typeparam>
        /// <param name="source">A <code>System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;</code> containing data</param>
        /// <returns></returns>
        public static Dictionary<string, int> Cast<TInKey, TInValue, TOutKey, TOutValue>(this Dictionary<string, string> source)
        {
            return source.ToDictionary(o => o.Key.ChangeType<string>(), o => o.Value.ChangeType<int>());
        }
        #endregion

        #region IEnumerable<T>
        #region Validation
        /// <summary>
        /// Evaluates a collection if it is iterable through Linq
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="value">Collection to evaluate</param>
        /// <param name="checkCount">TRUE: checks count > 0</param>
        /// <returns></returns>
        public static bool IsLinqIterable<TSource>(this IEnumerable<TSource> value, bool checkCount)
        {
            return !value.IsNull() ? (checkCount ? value.Count() > 0 : true) : false;
        }
        #endregion Validation

        /// <summary>
        /// Adds an object to the end of the <code>System.Collections.ObjectModel.Collection&lt;<paramref name="TSource"/>&gt; 
        /// and returns the modified collection</code>
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">Source collection to be added to</param>
        /// <param name="item">The object to be added to the end of the <code>System.Collections.ObjectModel.Collection&lt;<paramref name="TSource"/>&gt;.</code> 
        /// The value can be null for reference types.</param>
        /// <returns>Collection after adding <paramref name="item"/></returns>
        public static IEnumerable<TSource> AddItem<TSource>(this IEnumerable<TSource> source, TSource item)
        {
            ObservableCollection<TSource> res = source.ToObservableCollection();
            res.Add(item);

            return res.AsEnumerable();
        }

        /// <summary>
        /// Adds an object to the end of the <code>System.Collections.ObjectModel.Collection&lt;<paramref name="TSource"/>&gt; 
        /// and returns the modified collection</code>
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">Source collection to be added to</param>
        /// <param name="items">The objects to be added to the end of the <code>System.Collections.ObjectModel.Collection&lt;<paramref name="TSource"/>&gt;.</code> 
        /// The values can be null for reference types.</param>
        /// <returns>Collection after adding <paramref name="items"/></returns>
        public static IEnumerable<TSource> AddItems<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> items)
        {
            items._ForEach(val => source = source.AddItem(val));
            return source;
        }

        /// <summary>
        /// Removes the first occurrence of a specific object from the <code>System.Collections.ObjectModel.Collection&lt;<paramref name="TSource"/>&gt;.</code>
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">Source collection to be removed from</param>
        /// <param name="item">The object to be added to the end of the <code>System.Collections.ObjectModel.Collection&lt;<paramref name="TSource"/>&gt;.</code> 
        /// The value can be null for reference types.</param>
        /// <returns>
        /// TRUE if item is successfully removed; otherwise, FALSE. This method also returns FALSE if item was not found in the original <code>System.Collections.ObjectModel.Collection&lt;<paramref name="TSource"/>&gt;.</code>
        /// </returns>
        public static IEnumerable<TSource> RemoveItem<TSource>(this IEnumerable<TSource> source, TSource item)
        {
            ObservableCollection<TSource> res = source.ToObservableCollection();
            if (res.Contains(item)) res.Remove(item);

            return res.AsEnumerable();
        }

        /// <summary>
        /// Removes the first occurrence of a specific object from the <code>System.Collections.ObjectModel.Collection&lt;<paramref name="TSource"/>&gt;.</code>
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">Source collection to be removed from</param>
        /// <param name="items">The objects to be added to the end of the <code>System.Collections.ObjectModel.Collection&lt;<paramref name="TSource"/>&gt;.</code> 
        /// The values can be null for reference types.</param>
        /// <returns>
        /// TRUE if item is successfully removed; otherwise, FALSE. This method also returns FALSE if item was not found in the original <code>System.Collections.ObjectModel.Collection&lt;<paramref name="TSource"/>&gt;.</code>
        /// </returns>
        public static IEnumerable<TSource> RemoveItems<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> items)
        {
            ObservableCollection<TSource> res = source.ToObservableCollection();
            foreach (TSource val in items) res = res.RemoveItem(val).ToObservableCollection();

            return res.AsEnumerable();
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <param name="value"></param>
        /// <param name="inclSpecifiedItem"></param>
        /// <returns></returns>
        public static IEnumerable<TSource> BeforeItems<TSource>(this IEnumerable<TSource> source, TSource value, bool inclSpecifiedItem)
        {
            ObservableCollection<TSource> res = new ObservableCollection<TSource>(source);
            if (res.Contains(value))
            {
                int i = res.IndexOf(value);
                res = new ObservableCollection<TSource>(res.Where(itm => inclSpecifiedItem ? res.IndexOf(itm) <= i : res.IndexOf(itm) < i));
            }

            return res.AsEnumerable();
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <param name="value"></param>
        /// <param name="inclSpecifiedItem"></param>
        /// <returns></returns>
        public static IEnumerable<TSource> AfterItems<TSource>(this IEnumerable<TSource> source, TSource value, bool inclSpecifiedItem)
        {
            ObservableCollection<TSource> res = new ObservableCollection<TSource>(source);
            if (res.Contains(value))
            {
                int i = res.IndexOf(value);
                res = new ObservableCollection<TSource>(res.Where(itm => inclSpecifiedItem ? res.IndexOf(itm) >= i : res.IndexOf(itm) > i));
            }

            return res.AsEnumerable();
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="source"></param>
        /// <param name="selector"></param>
        /// <returns></returns>
        public static bool HasDuplicate<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
        {
            foreach (TKey key in source.GroupBy(selector))
                if (source._Where(ts => ts.Equals(key)).HasCount(1, eComparers.NotEquals))
                    return true;

            return false;
        }

        public static long CountIf(this IEnumerable<string> value, string compare)
        {
            return value._Where(item => item == compare).GetCount();
        }

        public static ObservableCollection<string> AddDefaultItemAndSort(this IEnumerable<string> allItems, string defaultValue)
        {
            ObservableCollection<string> source = allItems.ToObservableCollection();
            if (!defaultValue.IsBlank()) source.Add(defaultValue);

            return source._OrderBy(val => val == defaultValue ? 0 : 1)._ThenBy(srs => srs).ToObservableCollection();
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string[] ToCharStringArray(this IEnumerable<char> value)
        {
            return value._Cast<string>().ToArray();
        }

        #region Custom/Advanced LINQ
        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <param name="value"></param>
        /// <param name="inclSpecifiedItem"></param>
        /// <returns></returns>
        public static IEnumerable<TSource> SkipTill<TSource>(this IEnumerable<TSource> source, TSource value, bool inclSpecifiedItem)
            where TSource : class
        {
            ObservableCollection<TSource> res = new ObservableCollection<TSource>(source);
            if (res.Contains(value))
            {
                int i = res.IndexOf(value);
                //res = new ObservableCollection<TSource>(res.Where(itm => inclSpecifiedItem ? res.IndexOf(itm) >= i : res.IndexOf(itm) > i));
                res = new ObservableCollection<TSource>(res.Skip(inclSpecifiedItem ? i + 1 : i));
            }

            return res.AsEnumerable();
        }

        /// <summary>
        /// Filters a sequence of values based on a predicate. Each element&apos;s index is used in the logic of the predicate function.
        /// </summary>
        /// <param name="source">An <code>System.Collections.Generic.IEnumerable&lt;TSource&gt;</code> to filter.</param>
        /// <param name="predicate">A function to test each source element for a condition; the second parameter of the function represents the index of the source element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// An <code>System.Collections.Generic.IEnumerable&lt;TSource&gt;</code> that contains elements from the input sequence that satisfy the condition.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or predicate is null.</exception>
        public static IEnumerable<TSource> SkipWhere<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
        {// RKD
            return source.Where(predicate).AsEnumerable();
        }

        /// <summary>
        /// Filters a sequence of values based on a predicate.
        /// </summary>
        /// <param name="source">An <code>System.Collections.Generic.IEnumerable&lt;TSource&gt;</code> to filter.</param>
        /// <param name="predicate">A function to test each element for a condition.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// An <code>System.Collections.Generic.IEnumerable&lt;TSource&gt;</code> that contains elements from the input sequence that satisfy the condition.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or predicate is null.</exception>
        public static IEnumerable<TSource> SkipWhere<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {// RKD
            return source.Where(predicate).AsEnumerable();
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public static IEnumerable<TSource> SkipWhereNot<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
        {// RKD
            return source.Where(src => !source.Where(predicate).Contains(src)).AsEnumerable();
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public static IEnumerable<TSource> SkipWhereNot<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {// RKD
            return source.Where(src => !source.Where(predicate).Contains(src)).AsEnumerable();
        }

        /// <summary>
        /// Performs the specified action on each element of the <code>System.Collections.Generic.IEnumerable&lt;TSource&gt;</code>
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">Collection to iterate through</param>
        /// <param name="action">The <code>System.Action&lt;TSource&gt;</code> delegate to perform on each element of the <code>System.Collections.Generic.IEnumerable&lt;TSource&gt;</code></param>
        /// <example>System.ArgumentNullException: action is null</example>
        public static void ForEach<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
        {
            source._ForEach<TSource>(action);
        }

        /// <summary>
        /// Sorts the elements of a sequence in ascending order according to a key
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <typeparam name="TKey">The type of the key returned by keySelector</typeparam>
        /// <param name="source">A sequence of values to order</param>
        /// <param name="keySelector">A function to extract a key from an element</param>
        /// <returns>An <code>System.Linq.IOrderedEnumerable&lt;TSource&gt;</code> whose elements are sorted according to a key</returns>
        // Exceptions:
        //   System.ArgumentNullException:
        //     source or keySelector is null.
        public static IOrderedEnumerable<TSource> OrderByDirection<TSource, TKey>(
            this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
            eSortDirection sortDirection = eSortDirection.Ascending)
        {
            switch (sortDirection)
            {
                case eSortDirection.Descending:
                    return source._OrderByDescending(keySelector);

                case eSortDirection.Ascending:
                default:
                    return source._OrderBy(keySelector);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="source"></param>
        /// <param name="keySelector"></param>
        /// <param name="isSortAscending"></param>
        /// <returns></returns>
        public static IOrderedEnumerable<TSource> OrderByDirection<TSource, TKey>(
            this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, bool isSortAscending)
        {
            return source.OrderByDirection(keySelector, GetSortDirection(isSortAscending));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <param name="propertyName"></param>
        /// <param name="sortDirection"></param>
        /// <returns></returns>
        public static IOrderedEnumerable<TSource> OrderByProperty<TSource>(
            this IEnumerable<TSource> source, string propertyName,
            eSortDirection sortDirection = eSortDirection.Ascending)
        {
            return source.OrderByDirection(val => val.GetType()
                .GetProperty(propertyName).GetValue(val, null), sortDirection);
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <param name="propertyName"></param>
        /// <param name="isSortAscending"></param>
        /// <returns></returns>
        public static IOrderedEnumerable<TSource> OrderByProperty<TSource>(
            this IEnumerable<TSource> source, string propertyName, bool isSortAscending)
        {
            return source.OrderByProperty(propertyName, GetSortDirection(isSortAscending));
        }

        /// <summary>
        /// Performs a subsequent ordering of the elements in a sequence in ascending order according to a key
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <typeparam name="TKey">The type of the key returned by keySelector</typeparam>
        /// <param name="source">An <code>System.Linq.IOrderedEnumerable&lt;TElement&gt;</code> that contains elements to sort</param>
        /// <param name="keySelector">A function to extract a key from each element</param>
        /// <param name="sortDirection">Sort direction</param>
        /// <returns>An <code>System.Linq.IOrderedEnumerable&lt;TElement&gt;</code> whose elements are sorted according to a key</returns>
        /// <exception cref="System.ArgumentNullException">source or keySelector is null.</exception>
        public static IOrderedEnumerable<TSource> ThenByDirection<TSource, TKey>(
            this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector,
            eSortDirection sortDirection = eSortDirection.Ascending)
        {
            switch (sortDirection)
            {
                case eSortDirection.Descending:
                    return source._ThenByDescending(keySelector);

                case eSortDirection.Ascending:
                default:
                    return source._ThenBy(keySelector);
            }
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="source"></param>
        /// <param name="keySelector"></param>
        /// <param name="isAscending"></param>
        /// <returns></returns>
        public static IOrderedEnumerable<TSource> ThenByDirection<TSource, TKey>(
            this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, bool isAscending)
        {
            return source.ThenByDirection(keySelector, GetSortDirection(isAscending));
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <param name="propertyName"></param>
        /// <param name="sortDirection"></param>
        /// <returns></returns>
        public static IOrderedEnumerable<TSource> ThenByProperty<TSource>(
            this IOrderedEnumerable<TSource> source,
            string propertyName, eSortDirection sortDirection = eSortDirection.Ascending)
        {
            return source.ThenByDirection(val => val.GetType()
                .GetProperty(propertyName).GetValue(val, null), sortDirection);
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <param name="propertyName"></param>
        /// <param name="isAscending"></param>
        /// <returns></returns>
        public static IOrderedEnumerable<TSource> ThenByProperty<TSource>(
            this IOrderedEnumerable<TSource> source, string propertyName, bool isAscending)
        {
            return source.ThenByProperty(propertyName, GetSortDirection(isAscending));
        }
        #endregion Custom/Advanced LINQ

        /// <summary>
        /// Checks count of a collection against specified value
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">Collection to be validated for count</param>
        /// <param name="count">Value to be validated against</param>
        /// <param name="comparer">Comparison type</param>
        /// <returns></returns>
        public static bool HasCount<TSource>(this IEnumerable<TSource> source, long count, eComparers comparer = eComparers.Equals)
        {
            return source.IsLinqIterable<TSource>(false) ? Utilities.CompareValues(source.GetCount(), count, comparer) : false;
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <param name="propName"></param>
        /// <returns></returns>
        public static IEnumerable<TSource> AddCollectionIndex<TSource>(this IEnumerable<TSource> source, string propName)
        {
            if (Utilities.HasProperty<TSource>(propName, false))
                source.ToList().ConvertAll(itm => itm = Utilities.SetValue(itm, propName, source.ToList().IndexOf(itm) + 1));

            return source.AsEnumerable();
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static ObservableCollection<TSource> ToObservableCollection<TSource>(this IEnumerable<TSource> source)
        {
            return source.IsNull() ? new ObservableCollection<TSource>() : new ObservableCollection<TSource>(source);
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="source"></param>
        /// <param name="converter"></param>
        /// <returns></returns>
        public static IEnumerable<TResult> ConvertAll<TSource, TResult>(this IEnumerable<TSource> source, Converter<TSource, TResult> converter)
        //public static IEnumerable<TResult> _ConvertAll< TResul>(this IEnumerable<TSource> source, Converter<TSource, TResult> converter)
        {
            IEnumerable<TResult> result = source.ToList().ConvertAll(converter);
            return result.AsEnumerable();
        }

        #region LINQ extensions (handles null collections)
        /// <summary>
        /// Determines whether a sequence contains no elements
        /// <para>(handles null collection)</para>
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">The <code>System.Collections.Generic.IEnumerable&lt;<paramref name="TSource"/>&gt;</code> to check for emptiness</param>
        /// <returns>TRUE if the source sequence contains any elements; otherwise FALSE</returns>
        public static bool _None<TSource>(this IEnumerable<TSource> source)
        {
            return !source._Any();
        }

        /// <summary>
        /// Determines whether a sequence contains no elements
        /// <para>(handles null collection)</para>
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">The <code>System.Collections.Generic.IEnumerable&lt;<paramref name="TSource"/>&gt;</code> to check for emptiness</param>
        /// <param name="predicate">An <code>System.Collections.Generic.IEnumerable&lt;<paramref name="TSource"/>&gt;</code> 
        /// that contains elements from the input sequence that satisfy the condition</param>
        /// <returns>TRUE if the source sequence contains any elements; otherwise FALSE</returns>
        public static bool _None<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {
            return source.Where(predicate)._None();
        }

        /// <summary>
        /// Filters a sequence of values based on a <paramref name="predicate"/>
        /// <para>(handles null collection)</para>
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">The <code>System.Collections.Generic.IEnumerable&lt;<paramref name="TSource"/>&gt;</code> to check for emptiness</param>
        /// <param name="predicate">An <code>System.Collections.Generic.IEnumerable&lt;<paramref name="TSource"/>&gt;</code> 
        /// that contains elements from the input sequence that satisfy the condition</param>
        /// <returns></returns>
        public static IEnumerable<TSource> _Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {
            if (source.IsNull()) return null;
            else return source.Where(predicate);
        }

        /// <summary>
        /// Determines whether a sequence contains any elements
        /// <para>(handles null collection)</para>
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">The <code>System.Collections.Generic.IEnumerable&lt;<paramref name="TSource"/>&gt;</code> to check for emptiness</param>
        /// <returns>TRUE if the source sequence contains any elements; otherwise FALSE</returns>
        public static bool _Any<TSource>(this IEnumerable<TSource> source)
        {
            if (source.IsNull()) return false;
            else return source.Any();
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public static bool _Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {
            return source._Where(predicate)._Any();
        }

        /// <summary>
        /// Determines whether all elements of a sequence satisfy a condition.
        /// </summary>
        /// <param name="source">An <code>System.Collections.Generic.IEnumerable&lt;<paramref name="TSource"/>&gt;</code> that contains the elements to apply the predicate to.</param>
        /// <param name="predicate">A function to test each element for a condition.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>TRUE if every element of the source sequence passes the test in the specified predicate, or if the sequence is empty;
        /// <para>otherwise, FALSE.</para></returns>
        /// <exception cref="System.ArgumentNullException">source or predicate is null.</exception>
        public static bool _All<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {
            if (source.IsNull()) return false;
            else return source.All(predicate);
        }

        /// <summary>
        /// Projects each element of a sequence into a new form by incorporating the element&apos;s index.
        /// </summary>
        /// <param name="source">A sequence of values to invoke a transform function on.</param>
        /// <param name="selector">A transform function to apply to each source element; the second parameter of the function represents the index of the source element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <typeparam name="TResult">The type of the value returned by selector.</typeparam>
        /// <returns>
        /// An <code>System.Collections.Generic.IEnumerable&lt;<paramref name="TSource"/>&gt;</code> whose elements are the result of invoking the transform function on each element of source.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        public static IEnumerable<TResult> _Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
        {
            if (source.IsNull()) return new ObservableCollection<TResult>();
            else return source.Select(selector);
        }

        /// <summary>
        /// Projects each element of a sequence into a new form.
        /// </summary>
        /// <param name="source">A sequence of values to invoke a transform function on.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <typeparam name="TResult">The type of the value returned by selector.</typeparam>
        /// <returns>
        /// An <code>System.Collections.Generic.IEnumerable&lt;<paramref name="TSource"/>&gt;</code> whose elements are the result of invoking the transform function on each element of source.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        public static IEnumerable<TResult> _Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
        {
            if (source.IsNull()) return new ObservableCollection<TResult>();
            else return source.Select(selector);
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public static IEnumerable<TSource> _ForEach<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
        {
            if (!source.IsNull()) source.ToList().ForEach(action);
            return source;
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IOrderedEnumerable<TSource> _OrderBy<TSource>(this IEnumerable<TSource> source)
            where TSource : struct
        {
            if (source.IsNull()) source = new ObservableCollection<TSource>();
            return source.OrderBy(item => item);
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IOrderedEnumerable<string> _OrderBy(this IEnumerable<string> source)
        {
            if (source.IsNull()) source = new ObservableCollection<string>();
            return source.OrderBy(item => item);
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="source"></param>
        /// <param name="keySelector"></param>
        /// <returns></returns>
        public static IOrderedEnumerable<TSource> _OrderBy<TSource, TKey>(
            this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            if (source.IsNull()) source = new ObservableCollection<TSource>();
            return source.OrderBy(keySelector);
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="source"></param>
        /// <param name="keySelector"></param>
        /// <returns></returns>
        public static IOrderedEnumerable<TSource> _OrderByDescending<TSource, TKey>(
           this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            if (source.IsNull()) source = new ObservableCollection<TSource>();
            return source.OrderByDescending(keySelector);
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IOrderedEnumerable<TSource> _ThenBy<TSource>(this IOrderedEnumerable<TSource> source)
            where TSource : struct
        {
            if (source.IsNull()) source = new ObservableCollection<TSource>()._OrderBy(val => val);
            return source.OrderBy(item => item);
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IOrderedEnumerable<string> _ThenBy(this IOrderedEnumerable<string> source)
        {
            if (source.IsNull()) source = new ObservableCollection<string>()._OrderBy(val => val);
            return source.OrderBy(item => item);
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="source"></param>
        /// <param name="keySelector"></param>
        /// <returns></returns>
        public static IOrderedEnumerable<TSource> _ThenBy<TSource, TKey>(
            this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            if (source.IsNull()) source = new ObservableCollection<TSource>()._OrderBy(val => val);
            return source.ThenBy(keySelector);
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="source"></param>
        /// <param name="keySelector"></param>
        /// <returns></returns>
        public static IOrderedEnumerable<TSource> _ThenByDescending<TSource, TKey>(
           this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            if (source.IsNull()) source = new ObservableCollection<TSource>()._OrderBy(val => val);
            return source.ThenByDescending(keySelector);
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TResult">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IEnumerable<TResult> _Cast<TResult>(this IEnumerable source)
        {
            if (source.IsNull()) return new ObservableCollection<TResult>();
            else return source.Cast<TResult>();
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool _Contains<TSource>(this IEnumerable<TSource> source, TSource value)
        {
            if (source.IsNull()) return false;
            else return source.Contains(value);
        }

        #region Aggregate methods
        #region Min
        /// <summary>
        /// Returns the minimum value in a generic sequence.
        /// </summary>
        /// <param name="source">A sequence of values to determine the minimum value of.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The minimum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        public static TSource _Min<TSource>(this IEnumerable<TSource> source)
        {
            if (!source.IsLinqIterable(true)) return default(TSource);
            else return source.Min();
        }

        /// <summary>
        /// Returns the minimum value in a sequence of <code>System.Decimal</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Decimal</code> values to determine the minimum value of.</param>
        /// <returns>
        /// The minimum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static decimal _Min(this IEnumerable<decimal> source)
        {
            if (!source.IsLinqIterable(true)) return default(decimal);
            else return source.Min();
        }

        /// <summary>
        /// Returns the minimum value in a sequence of <code>System.Double</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Double</code> values to determine the minimum value of.</param>
        /// <returns>
        /// The minimum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static double _Min(this IEnumerable<double> source)
        {
            if (!source.IsLinqIterable(true)) return default(double);
            else return source.Min();
        }

        /// <summary>
        /// Returns the minimum value in a sequence of <code>System.Single</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Single</code> values to determine the minimum value of.</param>
        /// <returns>
        /// The minimum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static float _Min(this IEnumerable<float> source)
        {
            if (!source.IsLinqIterable(true)) return default(float);
            else return source.Min();
        }

        /// <summary>
        /// Returns the minimum value in a sequence of <code>System.Int32</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Int32</code> values to determine the minimum value of.</param>
        /// <returns>
        /// The minimum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static int _Min(this IEnumerable<int> source)
        {
            if (!source.IsLinqIterable(true)) return default(int);
            else return source.Min();
        }

        /// <summary>
        /// Returns the minimum value in a sequence of <code>System.Int64</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Int64</code> values to determine the minimum value of.</param>
        /// <returns>
        /// The minimum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static long _Min(this IEnumerable<long> source)
        {
            if (!source.IsLinqIterable(true)) return default(long);
            else return source.Min();
        }

        /// <summary>
        /// Invokes a transform function on each element of a generic sequence and returns the minimum resulting value
        /// </summary>
        /// <param name="source">A sequence of values to determine the minimum value of</param>
        /// <param name="selector">A transform function to apply to each element</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <typeparam name="TResult">The type of the value returned by selector</typeparam>
        /// <returns>
        /// The minimum value in the sequence
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        public static TResult Min<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
        {
            if (!source.IsLinqIterable(true)) return default(TResult);
            else return source.Min(selector);
        }

        /// <summary>
        /// Invokes a transform function on each element of a sequence and returns the minimum <code>System.Decimal</code> value
        /// </summary>
        /// <param name="source">A sequence of values to determine the minimum value of.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The minimum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static decimal _Min<TSource>(this IEnumerable<TSource> source, Func<TSource, decimal> selector)
        {
            if (!source.IsLinqIterable(true)) return default(decimal);
            else return source.Min(selector);
        }

        /// <summary>
        /// Invokes a transform function on each element of a sequence and returns the minimum <code>System.Double</code> value.
        /// </summary>
        /// <param name="source">A sequence of values to determine the minimum value of.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The minimum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static double _Min<TSource>(this IEnumerable<TSource> source, Func<TSource, double> selector)
        {
            if (!source.IsLinqIterable(true)) return default(double);
            else return source.Min(selector);
        }

        /// <summary>
        /// Invokes a transform function on each element of a sequence and returns the minimum <code>System.Single</code> value.
        /// </summary>
        /// <param name="source">A sequence of values to determine the minimum value of.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The minimum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static float _Min<TSource>(this IEnumerable<TSource> source, Func<TSource, float> selector)
        {
            if (!source.IsLinqIterable(true)) return default(float);
            else return source.Min(selector);
        }

        /// <summary>
        /// Invokes a transform function on each element of a sequence and returns the minimum <code>System.Int32</code> value.
        /// </summary>
        /// <param name="source">A sequence of values to determine the minimum value of.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The minimum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static int _Min<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector)
        {
            if (!source.IsLinqIterable(true)) return default(int);
            else return source.Min(selector);
        }

        /// <summary>
        /// Invokes a transform function on each element of a sequence and returns the minimum <code>System.Int64</code> value.
        /// </summary>
        /// <param name="source">A sequence of values to determine the minimum value of.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The minimum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static long _Min<TSource>(this IEnumerable<TSource> source, Func<TSource, long> selector)
        {
            if (!source.IsLinqIterable(true)) return default(long);
            else return source.Min(selector);
        }
        #endregion

        #region Max
        /// <summary>
        /// Returns the maximum value in a generic sequence.
        /// </summary>
        /// <param name="source">A sequence of values to determine the maximum value of.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The maximum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        public static TSource _Max<TSource>(this IEnumerable<TSource> source)
        {
            if (!source.IsLinqIterable(true)) return default(TSource);
            else return source.Max();
        }

        /// <summary>
        /// Returns the maximum value in a sequence of <code>System.Decimal</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Decimal</code> values to determine the maximum value of.</param>
        /// <returns>
        /// The maximum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static decimal _Max(this IEnumerable<decimal> source)
        {
            if (!source.IsLinqIterable(true)) return default(decimal);
            else return source.Max();
        }

        /// <summary>
        /// Returns the maximum value in a sequence of <code>System.Double</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Double</code> values to determine the maximum value of.</param>
        /// <returns>
        /// The maximum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static double _Max(this IEnumerable<double> source)
        {
            if (!source.IsLinqIterable(true)) return default(double);
            else return source.Max();
        }

        /// <summary>
        /// Returns the maximum value in a sequence of <code>System.Single</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Single</code> values to determine the maximum value of.</param>
        /// <returns>
        /// The maximum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static float _Max(this IEnumerable<float> source)
        {
            if (!source.IsLinqIterable(true)) return default(float);
            else return source.Max();
        }

        /// <summary>
        /// Returns the maximum value in a sequence of <code>System.Int32</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Int32</code> values to determine the maximum value of.</param>
        /// <returns>
        /// The maximum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static int _Max(this IEnumerable<int> source)
        {
            if (!source.IsLinqIterable(true)) return default(int);
            else return source.Max();
        }

        /// <summary>
        /// Returns the maximum value in a sequence of <code>System.Int64</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Int64</code> values to determine the maximum value of.</param>
        /// <returns>
        /// The maximum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static long _Max(this IEnumerable<long> source)
        {
            if (!source.IsLinqIterable(true)) return default(long);
            else return source.Max();
        }

        /// <summary>
        /// Invokes a transform function on each element of a generic sequence and returns the maximum resulting value.
        /// </summary>
        /// <param name="source">A sequence of values to determine the maximum value of.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <typeparam name="TResult">The type of the value returned by selector.</typeparam>
        /// <returns>
        /// The maximum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        public static TResult _Max<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
        {
            if (!source.IsLinqIterable(true)) return default(TResult);
            else return source.Max(selector);
        }

        /// <summary>
        /// Invokes a transform function on each element of a sequence and returns the maximum <code>System.Decimal</code> value.
        /// </summary>
        /// <param name="source">A sequence of values to determine the maximum value of.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The maximum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static decimal _Max<TSource>(this IEnumerable<TSource> source, Func<TSource, decimal> selector)
        {
            if (!source.IsLinqIterable(true)) return default(decimal);
            else return source.Max(selector);
        }

        /// <summary>
        /// Invokes a transform function on each element of a sequence and returns the maximum <code>System.Double</code> value.
        /// </summary>
        /// <param name="source">A sequence of values to determine the maximum value of.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The maximum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static double _Max<TSource>(this IEnumerable<TSource> source, Func<TSource, double> selector)
        {
            if (!source.IsLinqIterable(true)) return default(double);
            else return source.Max(selector);
        }

        /// <summary>
        /// Invokes a transform function on each element of a sequence and returns the maximum <code>System.Single</code> value.
        /// </summary>
        /// <param name="source">A sequence of values to determine the maximum value of.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The maximum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static float _Max<TSource>(this IEnumerable<TSource> source, Func<TSource, float> selector)
        {
            if (!source.IsLinqIterable(true)) return default(float);
            else return source.Max(selector);
        }

        /// <summary>
        /// Invokes a transform function on each element of a sequence and returns the maximum <code>System.Int32</code> value.
        /// </summary>
        /// <param name="source">A sequence of values to determine the maximum value of.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The maximum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static int _Max<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector)
        {
            if (!source.IsLinqIterable(true)) return default(int);
            else return source.Max(selector);
        }

        /// <summary>
        /// Invokes a transform function on each element of a sequence and returns the maximum <code>System.Int64</code> value.
        /// </summary>
        /// <param name="source">A sequence of values to determine the maximum value of.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The maximum value in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static long _Max<TSource>(this IEnumerable<TSource> source, Func<TSource, long> selector)
        {
            if (!source.IsLinqIterable(true)) return default(long);
            else return source.Max(selector);
        }
        #endregion

        #region Average
        /// <summary>
        /// Computes the average of a sequence of <code>System.Decimal</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Decimal</code> values to calculate the average of.</param>
        /// <returns>
        /// The average of the sequence of values.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        /// <exception cref="System.OverflowException">The sum of the elements in the sequence is larger than <code>System.Decimal.MaxValue</code>.</exception>
        public static decimal _Average(this IEnumerable<decimal> source)
        {
            if (!source.IsLinqIterable(true)) return default(decimal);
            else return source.Average();
        }

        /// <summary>
        /// Computes the average of a sequence of <code>System.Double</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Double</code> values to calculate the average of.</param>
        /// <returns>
        /// The average of the sequence of values.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static double _Average(this IEnumerable<double> source)
        {
            if (!source.IsLinqIterable(true)) return default(double);
            else return source.Average();
        }

        /// <summary>
        /// Computes the average of a sequence of <code>System.Single</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Single</code> values to calculate the average of.</param>
        /// <returns>
        /// The average of the sequence of values.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static float _Average(this IEnumerable<float> source)
        {
            if (!source.IsLinqIterable(true)) return default(float);
            else return source.Average();
        }

        /// <summary>
        /// Computes the average of a sequence of <code>System.Int32</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Int32</code> values to calculate the average of.</param>
        /// <returns>
        /// The average of the sequence of values.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        /// <exception cref="System.OverflowException">The sum of the elements in the sequence is larger than <code>System.Int64.MaxValue.</code></exception>
        public static double _Average(this IEnumerable<int> source)
        {
            if (!source.IsLinqIterable(true)) return default(double);
            else return source.Average();
        }

        /// <summary>
        /// Computes the average of a sequence of <code>System.Int64</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Int64</code> values to calculate the average of.</param>
        /// <returns>
        /// The average of the sequence of values.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        /// <exception cref="System.OverflowException">The sum of the elements in the sequence is larger than <code>System.Int64.MaxValue.</code></exception>
        public static double _Average(this IEnumerable<long> source)
        {
            if (!source.IsLinqIterable(true)) return default(double);
            else return source.Average();
        }

        /// <summary>
        /// Computes the average of a sequence of <code>System.Decimal</code> values that are obtained by invoking a transform function on each element of the input sequence.
        /// </summary>
        /// <param name="source">A sequence of values that are used to calculate an average.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The average of the sequence of values.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        /// <exception cref="System.OverflowException">The sum of the elements in the sequence is larger than <code>System.Decimal.MaxValue</code>.</exception>
        public static decimal _Average<TSource>(this IEnumerable<TSource> source, Func<TSource, decimal> selector)
        {
            if (!source.IsLinqIterable(true)) return default(decimal);
            else return source.Average(selector);
        }

        /// <summary>
        /// Computes the average of a sequence of <code>System.Double</code> values that are obtained by invoking a transform function on each element of the input sequence.
        /// </summary>
        /// <param name="source">A sequence of values to calculate the average of.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The average of the sequence of values.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static double _Average<TSource>(this IEnumerable<TSource> source, Func<TSource, double> selector)
        {
            if (!source.IsLinqIterable(true)) return default(double);
            else return source.Average(selector);
        }

        /// <summary>
        /// Computes the average of a sequence of <code>System.Single</code> values that are obtained by invoking a transform function on each element of the input sequence.
        /// </summary>
        /// <param name="source">A sequence of values to calculate the average of.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The average of the sequence of values.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        public static float _Average<TSource>(this IEnumerable<TSource> source, Func<TSource, float> selector)
        {
            if (!source.IsLinqIterable(true)) return default(float);
            else return source.Average(selector);
        }

        /// <summary>
        /// Computes the average of a sequence of <code>System.Int32</code> values that are obtained by invoking a transform function on each element of the input sequence.
        /// </summary>
        /// <param name="source">A sequence of values to calculate the average of.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The average of the sequence of values.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        /// <exception cref="System.OverflowException">The sum of the elements in the sequence is larger than <code>System.Int64.MaxValue.</code></exception>
        public static double _Average<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector)
        {
            if (!source.IsLinqIterable(true)) return default(double);
            else return source.Average(selector);
        }

        /// <summary>
        /// Computes the average of a sequence of <code>System.Int64</code> values that are obtained by invoking a transform function on each element of the input sequence.
        /// </summary>
        /// <param name="source">A sequence of values to calculate the average of.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The average of the sequence of values.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.InvalidOperationException">source contains no elements.</exception>
        /// <exception cref="System.OverflowException">The sum of the elements in the sequence is larger than <code>System.Int64.MaxValue.</code></exception>
        public static double _Average<TSource>(this IEnumerable<TSource> source, Func<TSource, long> selector)
        {
            if (!source.IsLinqIterable(true)) return default(double);
            else return source.Average(selector);
        }
        #endregion

        #region Sum
        /// <summary>
        /// Computes the sum of a sequence of <code>System.Decimal</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Decimal</code> values to calculate the sum of.</param>
        /// <returns>
        /// The sum of the values in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.OverflowException">The sum is larger than <code>System.Decimal.MaxValue</code>.</exception>
        public static decimal _Sum(this IEnumerable<decimal> source)
        {
            if (!source.IsLinqIterable(true)) return default(decimal);
            else return source.Sum();
        }

        /// <summary>
        /// Computes the sum of a sequence of <code>System.Double</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Double</code> values to calculate the sum of.</param>
        /// <returns>
        /// The sum of the values in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        public static double _Sum(this IEnumerable<double> source)
        {
            if (!source.IsLinqIterable(true)) return default(double);
            else return source.Sum();
        }

        /// <summary>
        /// Computes the sum of a sequence of <code>System.Single</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Single</code> values to calculate the sum of.</param>
        /// <returns>
        /// The sum of the values in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        public static float _Sum(this IEnumerable<float> source)
        {
            if (!source.IsLinqIterable(true)) return default(float);
            else return source.Sum();
        }

        /// <summary>
        /// Computes the sum of a sequence of <code>System.Int32</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Int32</code> values to calculate the sum of.</param>
        /// <returns>
        /// The sum of the values in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.OverflowException">The sum is larger than <code>System.Int32.MaxValue.</code></exception>
        public static int _Sum(this IEnumerable<int> source)
        {
            if (!source.IsLinqIterable(true)) return default(int);
            else return source.Sum();
        }

        /// <summary>
        /// Computes the sum of a sequence of <code>System.Int64</code> values.
        /// </summary>
        /// <param name="source">A sequence of <code>System.Int64</code> values to calculate the sum of.</param>
        /// <returns>
        /// The sum of the values in the sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.OverflowException">The sum is larger than <code>System.Int64.MaxValue.</code></exception>
        public static long _Sum(this IEnumerable<long> source)
        {
            if (!source.IsLinqIterable(true)) return default(long);
            else return source.Sum();
        }

        /// <summary>
        /// Computes the sum of the sequence of <code>System.Decimal</code> values that are obtained by invoking a transform function on each element of the input sequence.
        /// </summary>
        /// <param name="source">A sequence of values that are used to calculate a sum.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The sum of the projected values.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.OverflowException">The sum is larger than <code>System.Decimal.MaxValue</code>.</exception>
        public static decimal _Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, decimal> selector)
        {
            if (!source.IsLinqIterable(true)) return default(decimal);
            else return source.Sum(selector);
        }

        /// <summary>
        /// Computes the sum of the sequence of <code>System.Double</code> values that are obtained by invoking a transform function on each element of the input sequence.
        /// </summary>
        /// <param name="source">A sequence of values that are used to calculate a sum.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The sum of the projected values.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        public static double _Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, double> selector)
        {
            if (!source.IsLinqIterable(true)) return default(double);
            else return source.Sum(selector);
        }

        /// <summary>
        /// Computes the sum of the sequence of <code>System.Single</code> values that are obtained by invoking a transform function on each element of the input sequence.
        /// </summary>
        /// <param name="source">A sequence of values that are used to calculate a sum.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The sum of the projected values.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        public static float _Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, float> selector)
        {
            if (!source.IsLinqIterable(true)) return default(float);
            else return source.Sum(selector);
        }

        /// <summary>
        /// Computes the sum of the sequence of <code>System.Int32</code> values that are obtained by invoking a transform function on each element of the input sequence.
        /// </summary>
        /// <param name="source">A sequence of values that are used to calculate a sum.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The sum of the projected values.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.OverflowException">The sum is larger than <code>System.Int32.MaxValue.</code></exception>
        public static int _Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector)
        {
            if (!source.IsLinqIterable(true)) return default(int);
            else return source.Sum(selector);
        }

        /// <summary>
        /// Computes the sum of the sequence of <code>System.Int64</code> values that are obtained by invoking a transform function on each element of the input sequence.
        /// </summary>
        /// <param name="source">A sequence of values that are used to calculate a sum.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The sum of the projected values.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source or selector is null.</exception>
        /// <exception cref="System.OverflowException">The sum is larger than <code>System.Int64.MaxValue.</code></exception>
        public static long _Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, long> selector)
        {
            if (!source.IsLinqIterable(true)) return default(long);
            else return source.Sum(selector);
        }
        #endregion
        #endregion Aggregate methods
        #endregion

        #region SingletonValueWrapper
        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static IEnumerable<SingletonValueWrapper<TSource>> ConvertToSingletonValueWrapper<TSource>(this IEnumerable<TSource> value)
        {
            return SingletonValueWrapper<TSource>.ConvertToSingletonValueWrapper(value);
        }
        #endregion SingletonValueWrapper
        #endregion LINQ extensions (handles null collections)

        #region General
        /// <summary>
        /// Returns a single value. -- RKD
        /// If <paramref name="value"/> is Null, returns default value of type <paramref name="TSource"/>;
        /// else returns the First item
        /// <para>Can be used instead of FirstOrDefault() defined under <code>System.Linq</code></para>
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static TSource GetValue<TSource>(this IEnumerable<TSource> value)
        {
            if (value.IsNull()) return default(TSource);
            else if (!value.IsNull() && !value.Any()) return default(TSource);
            else return value.First();
        }

        /// <summary>
        /// RKD - add xml docum
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <typeparam name="TResult">The type of objects to return</typeparam>
        /// <param name="source">An <code>System.Collections.Generic.IEnumerable&lt;TSource&gt;</code> that contains the elements to be counted.</param>
        /// <returns></returns>
        public static TResult GetValue<TSource, TResult>(this IEnumerable<TSource> source)
           where TResult : TSource
        {
            if (source.IsNull()) return default(TResult);
            else if (!source.IsNull() && !source.Any()) return default(TResult);
            else return (TResult)source.First();
        }

        /// <summary>
        /// Returns an <code>System.Int64</code> that represents the total number of elements in a sequence.
        /// </summary>
        /// <param name="source">An <code>System.Collections.Generic.IEnumerable&lt;TSource&gt;</code> that contains the elements to be counted.</param>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <returns>
        /// The number of elements in the source sequence.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">source is null.</exception>
        /// <exception cref="System.OverflowException">The number of elements exceeds <code>System.Int64.MaxValue.</code></exception>
        public static long GetCount<TSource>(this IEnumerable<TSource> source)
        {
            if (source.IsNull()) return 0;
            else return source.LongCount();
        }
        #endregion General
        #endregion IEnumerable<T>

        //using (IdNameValueMember idv = new IdNameValueMember())
        //{
        //    List<Expression<Func<IdNameValueMember, bool>>> whrecls = new List<Expression<Func<IdNameValueMember, bool>>>();
        //    whrecls.Add(z => z.Id.ToString() == z.Name.ToString());
        //    whrecls.Add(z => z.Id.GetType() == z.Name.GetType());
        //
        //    List<IdNameValueMember> op = new List<IdNameValueMember>();
        //    op = op.Select(whrecls).ToList();
        //}

        /*
        /// <summary>
        /// This method returns the current item of the given collection.
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">The collection.</param>
        public static TSource GetCurrentItem<TSource>(this IEnumerable<TSource> source)
        {
            if (source.IsNull())
                return default(TSource);
            var collectionView = CollectionViewSource.GetDefaultView(source);
            return (TSource)collectionView.CurrentItem;
        }

        /// <summary>
        /// This method returns the current position within the given collection.
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">The collection.</param>
        public static int GetCurrentPosition<TSource>(this IEnumerable<TSource> source)
        {
            if (source.IsNull())
                return -1;
            var collectionView = CollectionViewSource.GetDefaultView(source);
            return collectionView.CurrentPosition;
        }

        /// <summary>
        /// This method sets the current item of the given collection.
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">The collection.</param>
        /// <param name="item">The item which should be set as the current one.</param>
        public static void SetCurrentItem<TSource>(this IEnumerable<TSource> source, TSource item)
        {
            if (source.IsNull()) return;
            var collectionView = CollectionViewSource.GetDefaultView(source);
            collectionView.MoveCurrentTo(item);
        }

        /// <summary>
        /// This method moves the current item to the first.
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">The collection.</param>
        public static void MoveCurrentToFirst<TSource>(this IEnumerable<TSource> source)
        {
            if (source.IsNull()) return;
            var collectionView = CollectionViewSource.GetDefaultView(source);
            collectionView.MoveCurrentToFirst();
        }

        /// <summary>
        /// This method moves the current item to the previous.
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">The collection.</param>
        public static void MoveCurrentToPrevious<TSource>(this IEnumerable<TSource> source)
        {
            if (source.IsNull()) return;
            var collectionView = CollectionViewSource.GetDefaultView(source);
            collectionView.MoveCurrentToPrevious();
        }

        /// <summary>
        /// This method moves the current item to the next.
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">The collection.</param>
        public static void MoveCurrentToNext<TSource>(this IEnumerable<TSource> source)
        {
            if (source.IsNull()) return;
            var collectionView = CollectionViewSource.GetDefaultView(source);
            collectionView.MoveCurrentToNext();
        }

        /// <summary>
        /// This method moves the current item to the last.
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">The collection.</param>
        public static void MoveCurrentToLast<TSource>(this IEnumerable<TSource> source)
        {
            if (source.IsNull()) return;
            var collectionView = CollectionViewSource.GetDefaultView(source);
            collectionView.MoveCurrentToLast();
        }

        /// <summary>
        /// This method sets the current position withing the given collection
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">The collection</param>
        /// <param name="index">The new position</param>
        public static void SetCurrentPosition<TSource>(this IEnumerable<TSource> source, int index)
        {
            if (source.IsNull()) return;
            var collectionView = CollectionViewSource.GetDefaultView(source);
            collectionView.MoveCurrentToPosition(index);
        }

        /// <summary>
        /// Removes the items from the collection according to the predicate.
        /// </summary>
        /// <typeparam name="TSource">The type of objects to enumerate. This type parameter is covariant. 
        /// <para>That is, you can use either the type you specified or any type that is more derived.</para>
        /// <para>For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</para></typeparam>
        /// <param name="source">The source.</param>
        /// <param name="predicate">The predicate.</param>
        public static void Remove<TSource>(this ICollection<TSource> source, Func<TSource, bool> predicate)
        {
            if (source.IsNull()) return;
            var itemsToRemove = source.Where(predicate).ToList();
            foreach (var item in itemsToRemove)
                source.Remove(item);
        }
        */

        #region Methods
        /// <summary>
        /// Gets the sort direction: ascending/descending
        /// </summary>
        /// <param name="isAscending"></param>
        /// <returns></returns>
        private static eSortDirection GetSortDirection(bool isAscending)
        {
            return isAscending ? eSortDirection.Ascending : eSortDirection.Descending;
        }

        /// <summary>
        /// Returns the full name of the class type
        /// </summary>
        /// <returns></returns>
        public static string ToString()
        {
            return Utilities.ToString(typeof(CollectionExtensions));
        }
        #endregion
    }
}
